/*
 * @Author: llch
 * @Date: 2020-09-21 09:11:43
 * @LastEditTime: 2021-04-18 09:02:26
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \tower_defense_demo\assets\scripts\game_scene\enemy\enemy.ts
 */

import { EnemyState, EnemyDirection, EnemyAttr } from "../../game_data/enemy_data/enemy_data"
import { EnemyBase } from "../enemy/enemy_base"
import { FrameAnim } from "../../common/frame_anim"
import { UG } from "../../modules/ugame";

const { ccclass, property } = cc._decorator;

// 自定义类
@ccclass("walk_anim_params")
class walk_anim_params {
    @property(cc.SpriteFrame)
    public anim_frames: cc.SpriteFrame[] = [];

    @property(cc.Integer)
    public anim_duration = 0.1;

    @property(cc.Integer)
    public scale_x = 1;
}

@ccclass
export default class Enemy extends cc.Component {

    public anim: cc.Node = null;            // 执行动画的节点
    public sprite_com: cc.Sprite = null;    // 播放动画的精灵组件
    public anim_com: cc.Animation = null;   // 动画组件
    public frame_anim: FrameAnim = null;    // 保存自定义动画组件

    @property(cc.ProgressBar)               // 血条组件
    public blood_bar: cc.ProgressBar = null;
    @property(cc.Node)                      // 用来播放动画的节点
    public anim_node: cc.Node = null;
    @property(cc.Label)
    public blood_label: cc.Label = null;    // 怪物血条数值

    // 行走的帧动画     0上，1下，2左，3右
    @property({
        type: walk_anim_params,
        tooltip: "0上，1下，2左，3右",
    })
    public walk_anim_data = [];

    // 变量
    public road_data: cc.Vec2[] = [];       // 当前路径的数据
    public enemy_obj: EnemyBase = null;     // 敌人基类
    public next_step: number = 1;           // 行走的节点索引
    public walk_time_total: number = undefined;     // 运动到下一个点的时间
    public walk_time: number = undefined;           // 怪物已经行走的时间
    public anim_dir: number = undefined;            // 怪物移动方向保存
    public enemy_params = null;             // 怪物配置

    public vx: number = undefined;          // x轴方向的速度
    public vy: number = undefined;          // y轴方向的速度

    public is_paused: boolean = false;      // 记录游戏暂停

    public game_scene = null;

    onLoad() {

        // 给自定义组件绑定精灵、动画组件
        this.anim = this.node.getChildByName("anim");
        this.frame_anim = this.node.addComponent(FrameAnim);
        this.frame_anim.sprite_com = this.anim.getComponent(cc.Sprite);
        this.frame_anim.anim_com = this.anim.getComponent(cc.Animation);
        
        // 怪物初始运动
        this.frame_anim.sprite_frame_arr = this.walk_anim_data[0].anim_frames;
        this.frame_anim.sample = this.walk_anim_data[0].anim_duration;
        this.anim.scaleX = this.walk_anim_data[0].scale_x;
        this.frame_anim.play_loop(true);

        this.game_scene = cc.find('Canvas/game_scene').getComponent('game_scene');
    }

    // 初始化怪物参数
    public init_enemy(enemy_params: object): void {
        this.enemy_params = enemy_params;
        this.enemy_obj = new EnemyBase(enemy_params);
        this.blood_label.string = this.enemy_obj.enemy_health.toString();
    }

    // 在指定路径上生成一个怪物
    public gen_at_road(road_data): void {
        if (road_data.length < 2) {
            return;
        }

        this.road_data = road_data;

        this.enemy_obj.set_enemy_state(EnemyState.WALK);    // 设置怪物状态为行走
        this.node.setPosition(road_data[0]);                // 设置怪物初始位置
        this.next_step = 1;                                 // 走向下一个节点索引
        this._walk_to_next();
    }

    // 走下一个索引点
    private _walk_to_next(): void {
        this.enemy_obj.enemy_state = EnemyState.WALK;           // 行走状态

        let start_pos: cc.Vec2 = this.node.getPosition();       // 获取当前的位置
        let end_pos: cc.Vec2 = this.road_data[this.next_step];  // 下一个点的位置
        let dir: cc.Vec2 = end_pos.sub(start_pos);              // 终点-起点，向量
        let len: number = dir.mag();                            // 向量长度

        this.walk_time_total = len / this.enemy_obj.enemy_speed;    // 距离除以时间，当前点运动到下一个点的时间
        // 计算速度方向
        this.vx = this.enemy_obj.enemy_speed * dir.x / len;         // x方向的速度
        this.vy = this.enemy_obj.enemy_speed * dir.y / len;         // y方向的速度
        this.walk_time = 0;                                         // 怪物已经行走的时间

        // 行走配合方向
        this.play_walk(dir);
    }

    // 播放当前行走方向的动画
    public play_walk(dir: cc.Vec2): void {
        // 通过角度来计算敌人朝向   Math.atan2来计算方位角，范围为-pi,pi
        // [-PI, -3/4PI) 左, [-3/4PI, -1/4PI) 下, [-1/4PI, 1/4PI) 右边, [1/4PI, 3/4PI) 上, [3/4PI, PI] 左
        let _r: number = Math.atan2(dir.y, dir.x);
        let _now_dir: number = EnemyDirection.INVALID_DIR;
        if (_r >= -Math.PI && _r < -0.75 * Math.PI) {                    // 左
            _now_dir = EnemyDirection.LEFT_DIR;
        } else if (_r >= -0.75 * Math.PI && _r < -0.25 * Math.PI) {      // 下
            _now_dir = EnemyDirection.DOWN_DIR;
        } else if (_r >= -0.25 * Math.PI && _r < 0.25 * Math.PI) {       // 右
            _now_dir = EnemyDirection.RIGHT_DIR;
        } else if (_r >= 0.25 * Math.PI && _r < 0.75 * Math.PI) {        // 上
            _now_dir = EnemyDirection.UP_DIR;
        } else {
            _now_dir = EnemyDirection.LEFT_DIR;                          // 否则统一为左   
        }
        // 如果方向不变，直接返回
        if (_now_dir === this.anim_dir) {
            return;
        }
        this.anim_dir = _now_dir;
        // 先把当前的动画停止
        this.frame_anim.stop_anim();
        this.frame_anim.sprite_frame_arr = this.walk_anim_data[this.anim_dir].anim_frames;
        this.frame_anim.sample = this.walk_anim_data[this.anim_dir].anim_duration;
        this.anim.scaleX = this.walk_anim_data[this.anim_dir].scale_x;

        this.frame_anim.play_loop(true);
    }

    // 行走更新
    public walk_update(dt: number): void {
        if (this.enemy_obj.enemy_state !== EnemyState.WALK) {
            return;
        }

        this.walk_time += dt;
        if (this.walk_time >= this.walk_time_total) {   // 已走到尽头
            dt -= (this.walk_time - this.walk_time_total);  // 去掉多余的时间
        }

        let sx: number = this.vx * dt;
        let sy: number = this.vy * dt;

        this.node.x += sx;
        this.node.y += sy;

        if (this.walk_time >= this.walk_time_total) {   // 当前已经到达的这个节点，走向下一个节点
            this.next_step++;
            if (this.next_step >= this.road_data.length) {  // 地图路径全部走完，则攻击玩家
                this.enemy_obj.enemy_state = EnemyState.ARRIVED;
                // 攻击玩家
                this._attack_player();
            } else {    // 未到达终点，继续前进
                this._walk_to_next();
            }
        }
    }

    // 计算某个时间后,移动到的位置
    public walk_pos_by_time(time: number): cc.Vec2 {
        // 不是行走状态,返回当前位置
        if (this.enemy_obj.enemy_state !== EnemyState.WALK) {
            return this.node.getPosition();
        }

        // 计算固定时间内,敌人移动到的位置
        let prev_pos: cc.Vec2 = this.node.getPosition();
        let next_step: number = this.next_step;

        if (time > 0) {
            for (next_step; next_step < this.road_data.length; next_step++) {
                let now_pos: cc.Vec2 = this.road_data[next_step];
                let dir: cc.Vec2 = now_pos.sub(prev_pos);
                let len: number = dir.mag();
                
                let _t: number = len / this.enemy_obj.enemy_speed;
                if (time > _t) {
                    time -= _t;
                    prev_pos = now_pos;
                } else {
                    const vx: number = this.enemy_obj.enemy_speed * dir.x / len;    // 三角函数
                    const vy: number = this.enemy_obj.enemy_speed * dir.y / len;    
                    const sx: number = vx * time;
                    const sy: number = vy * time;

                    prev_pos.x += sx;
                    prev_pos.y += sy;
                    return prev_pos;
                }
            }
        }

        // 否则返回地图最后一个点
        return this.road_data[next_step - 1];
    }

    update(dt) {
        // 
        if (this.enemy_obj.enemy_state === EnemyState.WALK) {
            this.walk_update(dt);
        }
    }

    // 敌人攻击玩家事件
    private _attack_player(): void {
        // 这里写玩家被攻击事件 
        this.game_scene.on_player_attacked(this.enemy_obj.palyer_hurt);
        // 移除敌人
        UG.remove_enemy(this.node);
        this.node.removeFromParent();
    }

    // 怪物被子弹攻击封装
    private _enemy_is_attacked(hurt_value: number): void {
        this.enemy_obj.enemy_health -= hurt_value;
        if (this.enemy_obj.enemy_health <= 0) {     // 怪物没血了
            this.enemy_obj.enemy_health = 0;
            // 获得奖励
            UG.add_chip(this.enemy_params.reward_chip);
            this.game_scene.show_game_uchip();

            this.enemy_obj.enemy_state = EnemyState.DEAD;
            UG.remove_enemy(this.node);

            // 播放怪物歇逼动画

            this.node.destroy();
        } else {    // 怪物没死，更新血条
            this.blood_label.string = this.enemy_obj.enemy_health.toString();
            this.blood_bar.progress = this.enemy_obj.enemy_health / this.enemy_params.health;
        }
    }

    // 怪物受到弓箭塔塔伤害
    public on_arrow_attacked(hurt_value: number): void {
        this._enemy_is_attacked(hurt_value);
    }

    // 怪物受到炮弹塔伤害
    public on_cannon_attacked(hurt_value: number): void {
        this._enemy_is_attacked(hurt_value);
    }

    // 怪物受到电击塔伤害
    public on_electricity_attacked(hurt_value: number): void {
        this._enemy_is_attacked(hurt_value);
    }

    // 怪物收到法师塔伤害
    public on_warlock_attacked(hurt_value: number): void {
        this._enemy_is_attacked(hurt_value);
    }

    // 怪物收到闪电技能伤害
    public on_skill_lightning_attacked(hurt_value: number): void {
        this._enemy_is_attacked(hurt_value);
    }
}